﻿using System;
using System.Collections.Generic;
using System.Linq;
using Budget.Core.Data;
using Budget.Core.DomainModel;
using Budget.Core.Extensions;
using Budget.Core.Specifications;
using Budget.Wcf.Core.Dto.Statistics;
using Budget.Wcf.Core.Interfaces;
using Castle.Core.Logging;

namespace Budget.Wcf.Services
{
    public class StatisticsService : BaseService, IStatisticsService
    {
        private readonly IRepository<OutcomeOrder> outcomeOrderRepo;

        public StatisticsService(ILogger logger, IRepository<OutcomeOrder> outcomeOrderRepo)
            : base(logger)
        {
            this.outcomeOrderRepo = outcomeOrderRepo;
        }

        public IList<StatisticByCategoryData> GetStatisticsByCategories(DateTime from, DateTime to)
        {
            try
            {
                var result = new List<StatisticByCategoryData>();
                var orders = outcomeOrderRepo.Find.All(OutcomeSpecifications.Range(from, to));
                var groupedOrders = orders.GroupBy(o => o.Product.Category);
                foreach (var group in groupedOrders)
                {
                    result.Add(new StatisticByCategoryData
                                   {
                                       CategoryName = group.Key.Name,
                                       Amount = group.Sum(o => o.Amount)
                                   });
                }

                return result;
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Details);
                return null;
            }
        }

        public IList<StatisticByYearData> GetStatisticsByYear()
        {
            try
            {
                var result = new List<StatisticByYearData>();
                var orders = outcomeOrderRepo.Find.All();
                var groupedOrders = orders.GroupBy(o => o.CreationDate.Year);
                foreach (var group in groupedOrders)
                {
                    result.Add(new StatisticByYearData
                                   {
                                       Year = group.Key,
                                       Amount = group.Sum(o => o.Amount)
                                   });
                }

                return result.OrderBy(data => data.Year).ToList();
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Details);
                return null;
            }
        }

        public IList<StatisticByMonthData> GetStatisticsByMonthes(DateTime from, DateTime to)
        {
            try
            {
                var result = new List<StatisticByMonthData>();
                var orders = outcomeOrderRepo.Find.All(OutcomeSpecifications.Range(from, to));
                var yearGroups = orders.GroupBy(o => o.CreationDate.Year).OrderBy(o => o.Key);
                foreach (var yearGroup in yearGroups)
                {
                    var monthGroups = yearGroup.GroupBy(o => o.CreationDate.Month).OrderBy(o => o.Key);
                    foreach (var monthGroup in monthGroups)
                    {
                        result.Add(new StatisticByMonthData
                                       {
                                           Month = new DateTime(from.Year, monthGroup.Key, 1).ToString("MMMM"),
                                           Amount = monthGroup.Sum(o => o.Amount)
                                       });
                    }
                }

                return result;
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Details);
                return null;
            }
        }
    }
}